/*
 * BooleanVector.cpp
 *
 * Copyright 2012 Fabian Wenzelmann
 *
 * This file is part of Recognition-Procedures-for-Boolean-Functions.
 *
 * Recognition-Procedures-for-Boolean-Functions is free software: you
 * can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * Recognition-Procedures-for-Boolean-Functions is distributed in the hope
 * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
 * Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Recognition-Procedures-for-Boolean-Functions.
 *
 * If not, see <http://www.gnu.org/licenses/>.
 */

#include "bfr/BooleanVector.hpp"

#include <stdarg.h>

#include <string>
#include <sstream>
#include <vector>

#include "bfr/Clause.hpp"

namespace bfr {

BooleanVector::BooleanVector()
    : point() { }

BooleanVector::BooleanVector(size_t initialSize, bool val)
    : point(initialSize, val) { }

BooleanVector::BooleanVector(const BooleanVector &other)
    : point(other.point) { }

BooleanVector::BooleanVector(const std::vector<bool> &vec)
    : point(vec) { }

BooleanVector::~BooleanVector() { }

void BooleanVector::append(size_t num, ...) {
    va_list vl;
    va_start(vl, num);
    for (size_t i = 0; i < num; i++) {
        int arg = va_arg(vl, int);
        push_back(arg);
    }
    va_end(vl);
}

Clause* BooleanVector::getHull(const BooleanVector &other) const {
    // TODO: maybe too much...
    if (size() != other.size()) {
        throw std::string("Can't compute hull because the vectors"
                " have a different dimension.");
    }
    Clause *c = new Clause(size());
    const_iterator otherIt = other.begin();
    size_t i = 0;
    for (const_iterator it = begin(); it != end(); it++) {
        assert (otherIt != other.end());
        if (*it != *otherIt) {
            otherIt++;
            i++;
            continue;
        }
        else {
            if (*otherIt) {
                // both are true
                c->add(Literal(i));
            }
            else {
                // both are false
                c->add(Literal(i, false));
            }
            otherIt++;
            i++;
        }
    }
    return c;
}

std::string BooleanVector::asString() const {
    std::ostringstream stream;
    stream << *this;
    return stream.str();
}

bool BooleanVector::operator ==(const BooleanVector &other) const {
    if (other.size() != size()) {
        throw std::string("Can't compare the Boolean vectors because they"
                " have a different dimension.");
    }
    const const_iterator e = end();
    const_iterator otherIt = other.begin();
    for (const_iterator it = begin(); it != e; it++) {
        assert (otherIt != other.end());
        if (*it != *otherIt)
            return false;
        otherIt++;
    }
    return true;
}

bool BooleanVector::operator !=(const BooleanVector &other) const {
    return !(operator ==(other));
}

} // namespace bfr
